import java.util.HashMap;

/**
 * 
 * @author Guillaume PANNETIER
 * @author Bertrand LE MAROUILLE
 * @author Quentin DORVEAUX
 * @author Corentin GUICHAOUA
 *
 */
public class TabIdent {
	private HashMap <String, Ident> locaux;
	private HashMap <String, IdFun> globaux; //Nom des fonctions
	private boolean fonctionOK=true; //dis si la fonction est OK
	/**
	 * Cette fonction initialise la table des locaux et celle des globaux.
	 * @param taille la taille des globaux
	 */
	public TabIdent(int taille){
		locaux = new HashMap <String, Ident> ();
		globaux = new HashMap <String, IdFun> (taille);
	}
	/**
	 * Cette fonction cherche un Ident dans la table des blogaux et celle des locaux et le renvoie.
	 * @param clef le nom de l'ident � chercher
	 * @return le nom de l'ident recherch�
	 * @throws TabIdentException
	 */
	public Ident chercheIdent(String clef) throws TabIdentException{
		if(existeIdent(clef)){
			return locaux.get(clef);
		}
		else if(globaux.containsKey(clef)){
			return globaux.get(clef);
		}
		else{
			throw new TabIdentException("Identificateur inconnu : "+clef);
		}
	}
	/**
	 * Cette fonction regarde si l'ident pass� en param�tre est pr�sent dans la table des locaux.
	 * @param clef le nom de l'ident recherch�
	 * @return vrai s'il est pr�sent, faux sinon
	 */
	public boolean existeIdent(String clef){
		return locaux.containsKey(clef);
	}
	/**
	 * Cette fonction place l'ident pass� en param�tre dans la table des locaux.
	 * @param clef le nom de l'ident � placer
	 * @param id l'ident � placer
	 * @throws TabIdentException
	 */
	public void rangeIdent(String clef, Ident id) throws TabIdentException{
		if(!existeIdent(clef))
			locaux.put(clef, id);
		else
			throw new TabIdentException("Identificateur deja declare : "+clef);
	}
	/**
	 * Cette fonction cherche le type de l'ident pass� en param�tre et le renvoie s'il est pr�sent dans la table des locaux ou celle des globaux.
	 * @param clef le nom de l'ident � chercher
	 * @return le type de l'ident recherch�
	 * @throws TabIdentException
	 */
	public int getType(String clef) throws TabIdentException{
		if(existeIdent(clef)){
			return locaux.get(clef).getType();
		}
		else if(globaux.containsKey(clef))
			return globaux.get(clef).getType();
		else
			throw new TabIdentException("Identificateur inconnu : "+clef);
	}
	/**
	 * Cette fonction recherche l'ident plac� en param�tre et renvoie sa valeur
	 * @param ident l'ident dont on cherche la valeur
	 * @return la valeur de l'ident pass� en param�tre (0 s'il n'est pas dans une table)
	 */

	public int getValue(String ident){
		try {
			return ((IdConst)(chercheIdent(ident))).getValeur();
		} catch (TabIdentException e) {
			Yaka.yvm.correct=false;
			Erreur.erreur(""+e.getMessage());
		}
		return 0;
	}
	/**
	 * Cette fonction vide la table des locaux.
	 */
	public void clearLocaux(){
		locaux.clear();
	}
	/**
	 * Cette fonction place une fonction dans la table des globaux.
	 * @param nom le nom de la fonction � placer dans la table des globaux
	 * @param retour le type de retour de la fonction
	 */
	public void addGlobal(String nom, int retour){
		if(globaux.containsKey(nom)){
			Erreur.erreur("Fonction déjà déclarée :"+nom);
			fonctionOK=false;
		}else{
			fonctionOK=true;
			globaux.put(nom, new IdFun(nom, retour));
		}
	}
	
	public void addArg(int arg){
		if(fonctionOK)
			globaux.get(YakaTokenManager.fonctionLue).addArg(Yaka.declaration.getDernierType());
	}
	
	public int getNbLocaux(){
		return locaux.size();
	}
	
	public int getNbVarCourant(){
		return locaux.size()-((IdFun)globaux.get(YakaTokenManager.fonctionLue)).getArgs().size();
	}
	
}
